﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Timers;
//g1.改进教材p412例9 - 10的爬虫程序，要求如下：
//（1）只爬取起始网站上的网页。
//（2）只有当爬取的是HTML文本时，才解析并爬取下一级URL。
//（3）相对地址转成绝对地址进行爬取。
//（4）尝试使用Winform来配置初始URL，启动爬虫，显示已经爬取的URL和错误的URL信息。

//g2.对输入框中输入的身份证是否合法进行验证：
//（1）使用正则表达式对格式进行验证（共18位，前17位为数字，最后1位是数字或字母，其中年月日部分也可以进行验证）；
//（2）对身份证的最后一位的有效性进行验证。

using Crawler;
using System.Text.RegularExpressions;
using System.Net;
using System.IO;

namespace CSharpWork07
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    ///     
    public class Record
    {
        public int index { set; get; }
    public string http { set; get; }
    public Record(int index, string http)
    {
        this.http = http;
        this.index = index;
    }
}
public partial class MainWindow : Window
    {
        public Hashtable urls = new Hashtable();
        public int count = 0;
        public List<Record> Rrecords { get; set; } = new List<Record>();
        public List<Record> Wrecords { get; set; } = new List<Record>();
        public string startUrl = "http://www.cnblogs.com/dstang2000/";
        Data data = new Data();
        public MainWindow()
        {
            InitializeComponent();
            data.Right = Rrecords;
            data.Wrong = Wrecords;
            right.DataContext = data;
            wrong.DataContext = data;
        }

        //public void refresh()
        //{
        //    right.ItemsSource = null;
        //    right.ItemsSource = Rrecords;
        //    wrong.ItemsSource = null;
        //    wrong.ItemsSource = Wrecords;
        //}

        public class Data
        {
            public List<Record> Right = new List<Record>();
            public List<Record> Wrong = new List<Record>();
        }

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {

            this.startUrl = textbox.Text;

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (startUrl == "") return;
            if (urls[startUrl] != null) return;
            urls.Add(startUrl, false);
            Task.Factory.StartNew(() =>
            {
                Crawle();
                this.Dispatcher.Invoke(() =>
                {
                    right.ItemsSource = null;
                    right.ItemsSource = Rrecords;
                    wrong.ItemsSource = null;
                    wrong.ItemsSource = Wrecords;
                });
            });
        }

        public void Crawle()
        {
            Regex isHtml = new Regex(@"<!DOCTYPE html>");
            while (true)
            {
                string current = null;
                foreach (string url in urls.Keys)
                {
                    if ((bool)urls[url]) continue;
                    current = url;
                }

                if (current == null || count > 10) break;

                string html = DownLoad(current);

                urls[current] = true;

                count++;

                if (isHtml.IsMatch(html))
                {
                    Parse(html);
                }
            }
        }

        public string DownLoad(string url)
        {
            try
            {
                WebClient webClient = new WebClient();
                webClient.Encoding = Encoding.UTF8;
                string html = webClient.DownloadString(url);

                string fileName = count.ToString();
                File.WriteAllText(fileName, html, Encoding.UTF8);

                return html;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return "";
            }
        }

        public void Parse(string html)
        {
            string strRef = "(?<=(href|HREF)=\")http\\S+(?=\")";

            Regex isHttp = new Regex(@"(?<=http)\S+");

            MatchCollection matches = new Regex(strRef).Matches(html);

            foreach (Match match in matches)
            {
                strRef = match.Value.Substring(match.Value.IndexOf('=') + 1).Trim('"', '\"', '#', '>');

                if (strRef.Length == 0) continue;

                if (urls[strRef] == null && isHttp.IsMatch(strRef))
                {
                    urls[strRef] = false;
                    Rrecords.Add(new Record(Rrecords.Count + 1, strRef));
                    //refresh();
                }
                else
                {
                    Wrecords.Add(new Record(Wrecords.Count + 1, strRef));
                    //refresh();
                }
            }
        }
    }
}
